/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
 */

package dao

import (
	"fmt"
	"prim-server/common"
	"prim-server/model"

	"github.com/astaxie/beego/orm"
	"github.com/pkg/errors"
	"github.com/spf13/cast"
)

type BalanceRecordDao struct {
	BaseDao
}

type IBalanceRecordDAo interface {
	SaveBalanceRecordInfo(balanceRecord *model.BalanceRecord) error
	DeleteBalanceRecordInfo(userId string) error
	UpdateBalanceRecordInfo(balanceRecord *model.BalanceRecord) error
	GetBalanceRecordInfo(queryParameter *common.QueryBalanceRecordDetail) (balanceRecords []*model.BalanceRecord, totalCount int, err error)
}

func GetBalanceRecordDao() IBalanceRecordDAo {
	dao := &BalanceRecordDao{}
	dao.Init()
	return dao
}

func (brd *BalanceRecordDao) SaveBalanceRecordInfo(balanceRecord *model.BalanceRecord) error {
	if balanceRecord == nil {
		return nil
	}
	_, err := brd.O.Insert(balanceRecord)
	if err != nil {
		_ = brd.O.Rollback()
		return errors.Errorf("SaveBalanceRecordInfo error: %v, balanceRecordId: %s", err, balanceRecord.BalanceRecordId)
	}
	return nil
}

func (brd *BalanceRecordDao) DeleteBalanceRecordInfo(userId string) error {
	if len(userId) == 0 {
		return nil
	}
	balanceRecord := new(model.BalanceRecord)
	balanceRecord.UserId = userId
	_, err := brd.O.Delete(balanceRecord, "user_id")
	if err != nil {
		_ = brd.O.Rollback()
		return errors.Errorf("DeleteBalanceRecordInfo error: %v, userId: %s", err, userId)
	}
	return nil
}
func (brd *BalanceRecordDao) UpdateBalanceRecordInfo(balanceRecord *model.BalanceRecord) error {
	if balanceRecord == nil {
		return nil
	}
	_, err := brd.O.Update(balanceRecord)
	if err != nil {
		_ = brd.O.Rollback()
		return errors.Errorf("UpdateBalanceRecordInfo error: %v, balanceRecord: %s", err, balanceRecord.BalanceRecordId)
	}
	return nil
}

func (brd *BalanceRecordDao) buildParameterForGetBalanceRecordInfo(queryParameter *common.QueryBalanceRecordDetail) *orm.Condition {
	finalCondition := orm.NewCondition()
	if len(queryParameter.BalanceRecordId) > 0 {
		finalCondition = finalCondition.And("balance_record_id__in", queryParameter.BalanceRecordId)
	}
	if len(queryParameter.UserId) > 0 {
		finalCondition = finalCondition.And("user_id__in", queryParameter.UserId)
	}
	if len(queryParameter.OperationType) > 0 {
		finalCondition = finalCondition.And("operation_type__in", queryParameter.OperationType)
	}
	if queryParameter.OperationTimeBegin != nil && queryParameter.OperationTimeEnd != nil {
		operationTimeCondition := orm.NewCondition()
		operationTimeCondition = operationTimeCondition.And("operation_time__gte", brd.ConvertToUTC(*queryParameter.OperationTimeBegin)).And("operation_time__lte", brd.ConvertToUTC(*queryParameter.OperationTimeEnd))
		finalCondition = finalCondition.AndCond(operationTimeCondition)
	}
	if queryParameter.Currency != nil {
		finalCondition = finalCondition.And("currency", *queryParameter.Currency)
	}
	if queryParameter.PaymentMethod != nil {
		finalCondition = finalCondition.And("payment_method", *queryParameter.PaymentMethod)
	}
	return finalCondition
}
func (brd *BalanceRecordDao) GetBalanceRecordInfo(queryParameter *common.QueryBalanceRecordDetail) (balanceRecords []*model.BalanceRecord, totalCount int, err error) {
	if queryParameter == nil {
		return nil, 0, nil
	}
	recode := brd.O.QueryTable(&model.BalanceRecord{})
	finalCondition := brd.buildParameterForGetBalanceRecordInfo(queryParameter)
	offset, pageSize := brd.GetOffsetAndPageSize(queryParameter.Page, queryParameter.PageSize)
	if queryParameter.TimeReverseOrder == nil {
		recode = recode.OrderBy("-operation_time")
	} else {
		if !(*queryParameter.TimeReverseOrder) {
			recode = recode.OrderBy("operation_time")
		}
	}
	recode = recode.SetCond(finalCondition)
	totalCount64, err := recode.Count()
	if err != nil {
		return nil, 0, errors.Errorf("GetBalanceRecordInfo error: %v, userId: %s", err, fmt.Sprint(queryParameter.UserId))
	}
	totalCount = cast.ToInt(totalCount64)
	_, err = recode.Offset(offset).Limit(pageSize).All(&balanceRecords)
	if err != nil {
		if err == orm.ErrNoRows {
			//not found
			return nil, 0, nil
		}
		//found error
		return nil, 0, errors.Errorf("GetBalanceRecordInfo error: %v, userId: %s", err, fmt.Sprint(queryParameter.UserId))
	}
	return balanceRecords, totalCount, nil
}
